# 作者： 迷路的小怪兽
# 创建时间： 2021/11/21 23:06
from api.tools.get_data import OperationExcel
from api.tools.get_data import OperationJson
from api.tools.get_data import OperationINI
import requests
import demjson
import time
from src.common.getlog import MyLog


class MainTest:
    """
    测试执行的主方法
    """

    def __init__(self):
        self.excel = OperationExcel()
        self.json = OperationJson()
        self.ini = OperationINI()
        self.case_num = self.excel.get_case_num()
        self.log = MyLog()
        # self.session = requests.session()
        # self.session.keep_alive = False

    def run_all(self):
        """
        运行所有的Excel中标记为运行的用例
        :return:
        """

        response_dir = {}  # 所有用例的响应存入此字典，如担心内存溢出，可以写一个方法，把内容写进文件保存

        for i in range(1, self.case_num):
            case_id = self.excel.get_case_id(i)
            id_list = self.excel.get_col_data()
            is_run = self.excel.get_is_run(i)
            if is_run == 'yes'or is_run == 'Yes' or is_run == 'YES':
                case_id = self.excel.get_case_id(i)
                case_depend = self.excel.get_case_depend(i)           # 用例依赖的case_id
                response_field = self.excel.get_response_field(i)     # 依赖数据所在的响应字段
                request_field = self.excel.get_request_field(i)       # 依赖数据所在的请求字段
                request_data_source = self.excel.get_request_data(i)  # 原始请求数据

                # 用例依赖目前解决思路：将每个用例id和最终响应以键值对存入字典
                # 用例依赖数据直接可以在该字典读取，避免依赖用例重复执行
                if case_depend == '' or case_depend is None:
                    response_data = self.run_this_case(case_id)
                    response_dir[case_id] = response_data
                    self.log.info('用例id为 %d 执行完成！' % case_id)

                elif case_depend != case_id:
                    res = response_dir[case_depend]
                    # 将响应中的依赖字段更新到请求数据中去
                    request_data_source[request_field] = res[response_field]
                    response_data = self.run_this_case(case_id, request_data_source)
                    response_dir[case_id] = response_data
                    self.log.info('用例id为 %d 依赖id为 %d 运行已完成！' %(case_id, case_depend))
            else:
                # case_id = self.excel.get_case_id(i)
                # id_list = self.excel.get_col_data()
                case_row_num = id_list.index(case_id) + 1
                self.write_result(case_row_num, '未执行！', '未执行！')
                self.log.info('用例id为 %s 未执行！' % case_id)

    def run_this_case(self, case_id, data=None):
        """
        执行一条用例
        :param case_id: 用例id
        :param data: 请求数据，若为None，则读取配置文件中原始数据
        :return: 返回该用例执行后的接口响应
        """
        id_list = self.excel.get_col_data()
        if case_id in id_list:
            row_num = id_list.index(case_id) + 1
            row_data_list = self.excel.get_row_data(row_num)
            url = row_data_list[2]
            request_method = row_data_list[3]

            if data is None:
                request_data = row_data_list[9]
            else:
                request_data = data

            expect_result = row_data_list[10]

            if row_data_list[4] == 'no' or row_data_list[4] == 'NO'\
                    or row_data_list[4] == 'No' or row_data_list[4] == '':
                header = None
            else:
                # 是否携带header列若携带header则需要标明header在json文件中的key
                header = self.json.get_data_from_json(row_data_list[4])

            res = self.send_request(request_method, url, request_data, header)
            # 将返回值编码成json字符串
            current_result = demjson.decode(res.text)

            # 可能有多个期望值，需要加上对应处理以英文逗号隔开
            result = 'Pass'
            expect_result_list = expect_result.split(',')
            for exp_res in expect_result_list:
                if not exp_res.split('=')[1] == str(current_result[expect_result.split('=')[0]]):
                    result = 'Fail'

            self.write_result(row_num, current_result, result)
            # 返回当前响应的结果字典
            return current_result
        else:
            # 记录日志
            error_msg = 'id %d 不存在，请仔细核实！' % case_id
            self.log.error(error_msg)

    def send_request(self, request_method, url, request_data=None, header=None):
        """
        发送请求
        :param request_method: 请求方法
        :param url: 请求的地址url
        :param request_data: 请求的数据字典
        :param header: 请求头部
        :return: 返回接口响应
        """
        res = None
        if request_method == 'get' or request_method == 'GET' or request_method == 'Get':
            res = requests.request('GET', url, params=request_data, headers=header)
        elif request_method == 'post' or request_method == 'POST' or request_method == 'Post':
            res = requests.request('POST', url, data=request_data, headers=header)
        else:
            # 记录日志
            error_msg = '请求方法填写错误，请检查！'
            self.log.error(error_msg)

        self.log.info('%s 接口数据已返回！' % url)
        return res

    def write_result(self, row, current_result, result):
        """
        往Excel中写测试结果
        :param row: 行数
        :param current_result: 当前结果
        :param result: 测试结论
        :return:
        """
        self.excel.add_current_result(row, current_result)
        self.excel.add_result(row, result)
        if current_result == '未执行！' and result == '未执行！':
            self.excel.add_date(row, '未执行！')
        else:
            self.excel.add_date(row, self.current_date())

    def current_date(self):
        """
        获取当前时间
        :return: 当前时间的字符串
        """
        return time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
